package batch

import (
	"encoding/json"
	"errors"
	"time"

	"github.com/golang/glog"
	v1 "k8s.io/api/apps/v1"

	apibatch "eccgateway/pkg/api/batch"
	dbbatch "eccgateway/pkg/db/batch"
)

var TemplateIsEmptyError = errors.New("template are not allowed to be empty")

func transformAPI2DB(input apibatch.Batch) dbbatch.Batch {
	failure, _ := json.Marshal(input.Failure)
	success, _ := json.Marshal(input.Success)
	pending, _ := json.Marshal(input.Pending)
	return dbbatch.Batch{
		ID:              input.ID,
		UserID:          input.UserID,
		Username:        input.Username,
		Name:            input.Name,
		Type:            input.Type,
		CreateTimestamp: input.CreateTimestamp,
		StartTimestamp:  input.StartTimestamp,
		EndTimestamp:    input.EndTimestamp,
		Status:          input.Status,
		Template:        input.Template,
		Failure:         string(failure),
		Success:         string(success),
		Pending:         string(pending),
	}
}

func transformDB2API(input dbbatch.Batch) apibatch.Batch {
	fails := []apibatch.Detail{}
	_ = json.Unmarshal([]byte(input.Failure), &fails)
	success := []apibatch.Detail{}
	_ = json.Unmarshal([]byte(input.Success), &success)
	pending := []apibatch.Detail{}
	_ = json.Unmarshal([]byte(input.Pending), &pending)
	return apibatch.Batch{
		ID:              input.ID,
		UserID:          input.UserID,
		Username:        input.Username,
		Name:            input.Name,
		Type:            input.Type,
		SuccessCount:    len(success),
		FailureCount:    len(fails),
		PendingCount:    len(pending),
		Status:          input.Status,
		CreateTimestamp: input.CreateTimestamp,
		StartTimestamp:  input.StartTimestamp,
		EndTimestamp:    input.EndTimestamp,
		Failure:         fails,
		Success:         success,
		Pending:         pending,
		Template:        input.Template,
	}
}

func transformDBs2APIs(input []dbbatch.Batch) []apibatch.Batch {
	res := make([]apibatch.Batch, 0, len(input))
	for _, v := range input {
		res = append(res, transformDB2API(v))
	}
	return res
}

func TransformTemplate2Deployment(input interface{}) (*v1.Deployment, error) {
	if input == nil {
		return nil, TemplateIsEmptyError
	}
	var err error
	var body []byte
	switch input.(type) {
	case string:
		body = []byte(input.(string))
	case []byte:
		body = input.([]byte)
	default:
		body, err = json.Marshal(input)
		if err != nil {
			return nil, err
		}
	}

	var deploy v1.Deployment
	err = json.Unmarshal(body, &deploy)
	return &deploy, err
}

func transformList2Pending(list []apibatch.Detail, BatchWorkName, Type string) []apibatch.Detail {
	t := time.Now()
	m := make(map[string]bool, len(list))
	res := make([]apibatch.Detail, 0, len(list))
	switch Type {
	case apibatch.CreateType:
		for _, v := range list {
			if m[v.Node] {
				continue
			}
			m[v.Node] = true
			res = append(res, apibatch.Detail{
				Cluster:    v.Cluster,
				Deployment: BatchWorkName + "-" + v.Node,
				Node:       v.Node,
				Namespace:  v.Namespace,
				Timestamp:  t,
			})
		}
	case apibatch.UpgradeType:
		for _, v := range list {
			if m[v.Deployment] {
				continue
			}
			m[v.Deployment] = true
			res = append(res, apibatch.Detail{
				Cluster:    v.Cluster,
				Deployment: v.Deployment,
				Node:       v.Node,
				Namespace:  v.Namespace,
				Timestamp:  t,
			})
		}
	default:
		glog.Errorf("type is invalid")
		return nil
	}
	return res
}
